# THIS IS NEW CMAKELISTS FILE !!!
cmake_minimum_required(VERSION 2.6)

# -----------------------------------------------------------------------------
# ----------------------------- Project configuration -------------------------
# -----------------------------------------------------------------------------

# -------------------------
# -- exes list and tools --
# -------------------------
set(MOD_FEM_EXEC_LIST)
set(MOD_FEM_TOOLS_LIST)

# Environment
set(ENV_PLATFORM $ENV{MOD_FEM_ARCH_CMAKE})
# perhaps MOD_FEM_ARCH was passed as argument?
if(NOT DEFINED ENV_PLATFORM)
    set(ENV_PLATFORM ${MOD_FEM_ARCH_CMAKE})
endif()

# Additional folders to search for CMake modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Platforms/")

# Set default CMAKE_BUILD_TYPE
if(DEFINED CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Choose build type")
else()
  set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose build type")
endif()
mark_as_advanced(CLEAR CMAKE_VERBOSE_MAKEFILE)

# Define project with languages
project(mod_fem_code)
enable_language(CXX)
enable_language(C)

#Binaries appendixes
set(DEBUG_POSTFIX "_d" )
set(RELWITHDEBINFO_POSTFIX "_i" )

# Builds directories
set(ARCHIVE_OUTPUT_PATH ${CMAKE_BUILD_TYPE} CACHE PATH "Subdirectory for archives" FORCE)
set(LIBRARY_OUTPUT_PATH ${CMAKE_BUILD_TYPE} CACHE PATH "Subdirectory for libraries" FORCE)
#set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BUILD_TYPE} CACHE PATH "Subdirectory for executables" FORCE)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR} CACHE PATH "Subdirectory for executables" FORCE)
mark_as_advanced(ARCHIVE_OUTPUT_PATH LIBRARY_OUTPUT_PATH EXECUTABLE_OUTPUT_PATH)

# Default compilation flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") 
if ( ${CMAKE_CXX_COMPILER_ID} STREQUAL GNU )
  set(CMAKE_CXX_FLAGS     "-Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable -Wno-comment ${CMAKE_CXX_FLAGS}  -pipe")
  set(CMAKE_C_FLAGS       "-Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable -Wno-comment ${CMAKE_C_FLAGS}  -pipe")
elseif( ${CMAKE_CXX_COMPILER_ID} STREQUAL Intel )
  #  set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -mp1 -assume nounderscore")
  set(CMAKE_CXX_FLAGS     "${CMAKE_CXX_FLAGS} -mp1 ")
elseif(MSVC)
  set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} /Qlowercase")  # For correct call to ilut,...
endif()
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -Dfloat='double'")

# -- PLATFORM --
# --------------
if(DEFINED ENV_PLATFORM)
  if(ENV_PLATFORM)
    if(EXISTS "${CMAKE_SOURCE_DIR}/cmake/Platforms/${ENV_PLATFORM}.cmake")
      include(${ENV_PLATFORM} CUSTOMPLATFORM_EXISTS)
      message(STATUS "MOD_FEM_ARCH_CMAKE is '${ENV_PLATFORM}'") # STATUS ????
      message(STATUS "File is ${CMAKE_SOURCE_DIR}/cmake/Platforms/${ENV_PLATFORM}.cmake") # STATUS ????
    else()
      message("MOD_FEM_ARCH_CMAKE is '${ENV_PLATFORM}'")
      message(FATAL_ERROR "File ${CMAKE_SOURCE_DIR}/cmake/Platforms/${ENV_PLATFORM}.cmake doesn't exist!")
    endif()  
  else()
    message(FATAL_ERROR "MOD_FEM_ARCH_CMAKE is not defined!")
  endif()
else()
  message(FATAL_ERROR "MOD_FEM_ARCH_CMAKE is not defined!")
endif()
  

# SVN revision 
# -------------------------
include(FindSubversion OPTIONAL)
IF(Subversion_FOUND)
  get_filename_component(CMAKE_SOURCE_DIR_REALPATH ${CMAKE_SOURCE_DIR} REALPATH)
  #MESSAGE("${CMAKE_SOURCE_DIR}") 
  set(ERR_VAR "")
  execute_process(COMMAND svn info 
    WORKING_DIRECTORY "${CMAKE_SOURCE_DIR_REALPATH}"
    ERROR_VARIABLE ERR_VAR
    )
  #MESSAGE("Trying svn message: ${ERR_VAR}")
  if(NOT ERR_VAR)
    #MESSAGE("Getting svn info...")
    Subversion_WC_INFO(${CMAKE_SOURCE_DIR_REALPATH} ModFEM)
    SET(SVN_REVISION "${ModFEM_WC_REVISION}")
    file(WRITE "${CMAKE_SOURCE_DIR_REALPATH}/include/svnversion.h" "const int SVNVERSION = ${SVN_REVISION} ;")
  endif()
ENDIF(Subversion_FOUND)

if(DEFINED SVN_REVISION)
    MESSAGE("Current revision is ${SVN_REVISION}")
else()
    MESSAGE("Current revision is not sync with local svn.")
endif()

# -- MODFEM_TEST_COVERAGE --
# -------------------------
set(MODFEM_TEST_COVERAGE_DEFAULT FALSE)
set(MODFEM_TEST_COVERAGE ${MODFEM_TEST_COVERAGE_DEFAULT} CACHE BOOL "Compilation with coverage tools (-fprofile-arcs -ftest-coverage) - default: FALSE")

if(MODFEM_TEST_COVERAGE)
  if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    if(NOT MODFEM_USE_STATIC)
      message(WARNING " -- Coverage testing does not work properly with shared libraries; Using static compilation")
      set(MODFEM_USE_STATIC ON)
    endif()
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
    set(CMAKE_FORTRAN_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
    set(LINK_FLAGS "${LINK_FLAGS}  -fprofile-arcs -ftest-coverage")
  else()
    message(WARNING " -- 'MODFEM_TEST_COVERAGE' is switched on while 'CMAKE_BUILD_TYPE' is not in 'Debug' mode; 'MODFEM_TEST_COVERAGE' is switched to false")
    set(MODFEM_TEST_COVERAGE FALSE)
  endif()
endif()

# -- MODFEM_USE_PROFILING --
# --------------------------
set(MODFEM_USE_PROFILING_DEFAULT FALSE)
set(MODFEM_USE_PROFILING ${MODFEM_USE_PROFILING_DEFAULT} CACHE BOOL "Enable profiling info (-pg) - default: ${MODFEM_USE_PROFILING_DEFAULT}")

if(MODFEM_USE_PROFILING)
  set(COMPILE_FLAGS "${COMPILE_FLAGS} -pg")
  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg")
else()
  if(DEFINED COMPILE_FLAGS)
    STRING(REPLACE "-pg" "" COMPILE_FLAGS ${COMPILE_FLAGS})
  endif()
  if(DEFINED CMAKE_EXE_LINER_FLAGS)
    STRING(REPLACE "-pg" "" CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS})
  endif()
endif()

# -- MODFEM_USE_STATIC --
# -----------------------
if(MODFEM_USE_STATIC)
  if(UNIX)
    set(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.so")
    message("-- Searching libraries will be done for static linking.")
  endif()
  set(BUILD_SHARED_LIBS FALSE)
else()
  if(UNIX)
    set(CMAKE_FIND_LIBRARY_SUFFIXES ".so;.a")
    message("-- Searching libraries will be done for dynamic linking.")
  endif()
  set(BUILD_SHARED_LIBS TRUE)
endif()

# OpenMP
find_package(OpenMP)
if(OPENMP_FOUND)
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
  if(NOT MSVC)
    set(LINK_FLAGS "${LINK_FLAGS} ${OpenMP_CXX_FLAGS}")  #'/openmp' not needed at link time
  endif()
endif()

# OpenCL
if(MODFEM_ACCEL)
  if(${MODFEM_ACCEL} STREQUAL "opencl")
    include_directories("${OPENCL_INCLUDE_DIRS}")
    link_directories("${OPENCL_LIBRARY_DIRS}")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lOpenCL")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lOpenCL")
    if(NOT MSVC)
      set(LINK_FLAGS "${LINK_FLAGS} -lOpenCL")
    endif()
  else()
    # ModFEM Viewer OpenCL
    if(CREATE_MOD_FEM_VIEWER)
      include_directories("${OPENCL_INCLUDE_DIRS}")
      link_directories("${OPENCL_LIBRARY_DIRS}")
      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lOpenCL")
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lOpenCL")
      if(NOT MSVC)
	set(LINK_FLAGS "${LINK_FLAGS} -lOpenCL")
      endif()
    endif()
  endif()
else()
  message(FATAL_ERROR "MODFEM_ACCEL not defined. Allowed values: none, opencl, cuda.")
endif()
 
# -----------------------------------------------------------------------------
# ----------------------------- Third-party libraries -------------------------
# -----------------------------------------------------------------------------

include(FindPackageHandleStandardArgs)  # Used in local find_package

# -----------------------------------------------------------------------------
# ------------------------- Functions -----------------------------------------
# -----------------------------------------------------------------------------
function(collect_src_from_include_dirs INCLUDE_DIRS)
  foreach(folder ${${INCLUDE_DIRS}})
    file(
      GLOB
      source_files_one_dir
      ${folder}/*.f
      ${folder}/*.F
      ${folder}/*.h
      ${folder}/*.hh
      ${folder}/*.hxx
      ${folder}/*.hpp
      ${folder}/*.cc
      ${folder}/*.cxx
      ${folder}/*.cpp
      ${folder}/*.c
    )
    list(APPEND SOURCE_FILES_LIST ${source_files_one_dir})
  endforeach()
  set(SOURCE_FILES ${SOURCE_FILES_LIST} PARENT_SCOPE)
endfunction()

# ---------------
# -- libconfig --
# ---------------

if( CREATE_MOD_FEM_HMT_PRISM_STD OR
    CREATE_MOD_FEM_HMT_HYBRID_STD OR
    CREATE_MOD_FEM_HMT_PRISM2D_STD OR

    CREATE_MOD_FEM_NS_SUPG_PRISM_STD OR
    CREATE_MOD_FEM_NS_SUPG_HYBRID_STD OR
    CREATE_MOD_FEM_NS_SUPG_PRISM2D_STD OR
    CREATE_MOD_FEM_NS_SUPG_PRISM_STD_TURBULENT OR
    CREATE_MOD_FEM_NS_SUPG_HYBRID_STD_TURBULENT OR
    CREATE_MOD_FEM_NS_SUPG_REMESH_STD OR
	
	CREATE_MOD_FEM_NS_SUPG_ALE_REMESH_STD OR

    CREATE_MOD_FEM_NS_SUPG_HEAT_PRISM_STD OR
    CREATE_MOD_FEM_NS_SUPG_HEAT_HYBRID_STD OR
    CREATE_MOD_FEM_NS_SUPG_HEAT_PRISM2D_STD OR
	CREATE_MOD_FEM_NS_SUPG_HEAT_REMESH_STD OR
	CREATE_MOD_FEM_NS_SUPG_HEAT_ALE_REMESH_STD OR
    
    CREATE_MOD_FEM_NS_SUPG_HEAT_VOF_PRISM_STD OR
    CREATE_MOD_FEM_NS_SUPG_HEAT_VOF_HYBRID_STD OR
    CREATE_MOD_FEM_NS_SUPG_HEAT_VOF_PRISM2D_STD
    )
    find_package(Libconfig REQUIRED)
    #set EXTERNAL_INCLUDE_DIRS of all supertargets that use library
    set(PDD_HMT_EXTERNAL_INCLUDE_DIRS ${PDD_HMT_EXTERNAL_INCLUDE_DIRS} ${LIBCONFIG_INCLUDE_DIRS})
    set(PDD_NS_SUPG_EXTERNAL_INCLUDE_DIRS ${PDD_NS_SUPG_EXTERNAL_INCLUDE_DIRS} ${LIBCONFIG_INCLUDE_DIRS})
    set(PDD_NS_SUPG_HEAT_EXTERNAL_INCLUDE_DIRS ${PDD_NS_SUPG_HEAT_EXTERNAL_INCLUDE_DIRS} ${LIBCONFIG_INCLUDE_DIRS})
    set(PDD_HEAT_EXTERNAL_INCLUDE_DIRS ${PDD_HEAT_EXTERNAL_INCLUDE_DIRS} ${LIBCONFIG_INCLUDE_DIRS})
    set(PDD_NS_SUPG_HEAT_VOF_EXTERNAL_INCLUDE_DIRS ${PDD_NS_SUPG_HEAT_VOF_EXTERNAL_INCLUDE_DIRS} ${LIBCONFIG_INCLUDE_DIRS})
    set(PDD_VOF_EXTERNAL_INCLUDE_DIRS ${PDD_VOF_EXTERNAL_INCLUDE_DIRS} ${LIBCONFIG_INCLUDE_DIRS})
    set(PDD_NS_SUPG_ALE_EXTERNAL_INCLUDE_DIRS ${PDD_NS_SUPG_ALE_EXTERNAL_INCLUDE_DIRS} ${LIBCONFIG_INCLUDE_DIRS})
	#set EXTERNAL_LIBRARIES of all supertargets that use library
    list(APPEND PDD_HMT_EXTERNAL_LIBRARIES ${LIBCONFIG_LIBRARIES})                     #pdd_hmt
    list(APPEND PDD_NS_SUPG_EXTERNAL_LIBRARIES ${LIBCONFIG_LIBRARIES})                 #pdd_ns_supg
    list(APPEND PDD_NS_SUPG_HEAT_EXTERNAL_LIBRARIES ${LIBCONFIG_LIBRARIES})            #pdd_ns_supg_heat
    list(APPEND PDD_NS_SUPG_ALE_EXTERNAL_LIBRARIES ${LIBCONFIG_LIBRARIES})             #pdd_ns_supg_ale
    list(APPEND PDD_HEAT_EXTERNAL_LIBRARIES ${LIBCONFIG_LIBRARIES})                    #pdd_heat
    list(APPEND PDD_NS_SUPG_PRISM_STD_TURBULENT_EXTERNAL_LIBRARIES ${LIBCONFIG_LIBRARIES}) #pdd_ns_supg_prism_std_turbulent
    list(APPEND PDD_NS_SUPG_HYBRID_STD_TURBULENT_EXTERNAL_LIBRARIES ${LIBCONFIG_LIBRARIES}) #pdd_ns_supg_hybrid_std_turbulent
    list(APPEND PDD_NS_SUPG_HEAT_VOF_EXTERNAL_LIBRARIES ${LIBCONFIG_LIBRARIES})        #pdd_ns_supg_heat_vof
    list(APPEND PDD_VOF_EXTERNAL_LIBRARIES ${LIBCONFIG_LIBRARIES})		       #pdd_vof
endif()

# ---------------
# -- voro++ --
# ---------------


  if( CREATE_MOD_FEM_NS_SUPG_HEAT_VOF_PRISM_STD OR
    CREATE_MOD_FEM_NS_SUPG_HEAT_VOF_HYBRID_STD OR
    CREATE_MOD_FEM_NS_SUPG_HEAT_VOF_PRISM2D_STD
    )
    find_package(VoroPP REQUIRED)
    #set EXTERNAL_INCLUDE_DIRS of all supertargets that use library
    set(PDD_HMT_EXTERNAL_INCLUDE_DIRS ${PDD_HMT_EXTERNAL_INCLUDE_DIRS} ${VOROPP_INCLUDE_DIRS})
    set(PDD_NS_SUPG_EXTERNAL_INCLUDE_DIRS ${PDD_NS_SUPG_EXTERNAL_INCLUDE_DIRS} ${VOROPP_INCLUDE_DIRS})
    set(PDD_NS_SUPG_HEAT_EXTERNAL_INCLUDE_DIRS ${PDD_NS_SUPG_HEAT_EXTERNAL_INCLUDE_DIRS} ${VOROPP_INCLUDE_DIRS})
    set(PDD_HEAT_EXTERNAL_INCLUDE_DIRS ${PDD_HEAT_EXTERNAL_INCLUDE_DIRS} ${VOROPP_INCLUDE_DIRS})
    set(PDD_NS_SUPG_HEAT_VOF_EXTERNAL_INCLUDE_DIRS ${PDD_NS_SUPG_HEAT_VOF_EXTERNAL_INCLUDE_DIRS} ${VOROPP_INCLUDE_DIRS})
    set(PDD_VOF_EXTERNAL_INCLUDE_DIRS ${PDD_VOF_EXTERNAL_INCLUDE_DIRS} ${VOROPP_INCLUDE_DIRS})
	set(PDD_NS_SUPG_ALE_EXTERNAL_INCLUDE_DIRS ${PDD_NS_SUPG_ALE_EXTERNAL_INCLUDE_DIRS} ${VOROPP_INCLUDE_DIRS})
    #set EXTERNAL_LIBRARIES of all supertargets that use library
    list(APPEND PDD_HMT_EXTERNAL_LIBRARIES ${VOROPP_LIBRARIES})                     #pdd_hmt
    list(APPEND PDD_NS_SUPG_EXTERNAL_LIBRARIES ${VOROPP_LIBRARIES})                 #pdd_ns_supg
    list(APPEND PDD_NS_SUPG_HEAT_EXTERNAL_LIBRARIES ${VOROPP_LIBRARIES})            #pdd_ns_supg_heat
	list(APPEND PDD_NS_SUPG_ALE_EXTERNAL_LIBRARIES ${VOROPP_LIBRARIES})             #pdd_ns_supg_ale
    list(APPEND PDD_HEAT_EXTERNAL_LIBRARIES ${VOROPP_LIBRARIES})                    #pdd_heat
    list(APPEND PDD_NS_SUPG_PRISM_STD_TURBULENT_EXTERNAL_LIBRARIES ${VOROPP_LIBRARIES}) #pdd_ns_supg_prism_std_turbulent
    list(APPEND PDD_NS_SUPG_HYBRID_STD_TURBULENT_EXTERNAL_LIBRARIES ${VOROPP_LIBRARIES}) #pdd_ns_supg_hybrid_std_turbulent
    list(APPEND PDD_NS_SUPG_HEAT_VOF_EXTERNAL_LIBRARIES ${VOROPP_LIBRARIES})        #pdd_ns_supg_heat_vof
    list(APPEND PDD_VOF_EXTERNAL_LIBRARIES ${VOROPP_LIBRARIES})		       #pdd_vof
    # -- pdd_vof ----
  endif()

# --------------------------------------------
# -- BLAS and Lapack (from MKL or standard) --
# --------------------------------------------

find_package(LapackMKL REQUIRED) #lapack/blas always required!
#set EXTERNAL_INCLUDE_DIRS of all supertargets that use library
set(SID_PARDISO_EXTERNAL_INCLUDE_DIRS ${SID_PARDISO_EXTERNAL_INCLUDE_DIRS} ${LAPACKMKL_INCLUDE_DIRS})
set(LSD_MKB_EXTERNAL_INCLUDE_DIRS ${SID_PARDISO_EXTERNAL_INCLUDE_DIRS} ${LAPACKMKL_INCLUDE_DIRS})
set(PDD_CBS_LIB_EXTERNAL_INCLUDE_DIRS ${PDD_CBS_LIB_EXTERNAL_INCLUDE_DIRS} ${LAPACKMKL_INCLUDE_DIRS})
set(PDD_CONV_DIFF_EXTERNAL_INCLUDE_DIRS ${PDD_CONV_DIFF_EXTERNAL_INCLUDE_DIRS} ${LAPACKMKL_INCLUDE_DIRS})
set(PDD_LAPLACE_EXTERNAL_INCLUDE_DIRS ${PDD_LAPLACE_EXTERNAL_INCLUDE_DIRS} ${LAPACKMKL_INCLUDE_DIRS})
set(SID_LAPACK_EXTERNAL_INCLUDE_DIRS ${SID_LAPACK_EXTERNAL_INCLUDE_DIRS} ${LAPACKMKL_INCLUDE_DIRS})
set(PDD_CBS_EXTERNAL_INCLUDE_DIRS ${PDD_CBS_EXTERNAL_INCLUDE_DIRS} ${LAPACKMKL_INCLUDE_DIRS})
set(PDD_TURBULENT_LIB_EXTERNAL_INCLUDE_DIRS ${PDD_TURBULENT_LIB_EXTERNAL_INCLUDE_DIRS} ${LAPACKMKL_INCLUDE_DIRS})

#set EXTERNAL_LIBRARIES of all targets that use library
list(APPEND SID_PARDISO_EXTERNAL_LIBRARIES ${LAPACKMKL_LIBRARIES})              #sid_pardiso
list(APPEND LSD_MKB_EXTERNAL_LIBRARIES ${LAPACKMKL_LIBRARIES})                  #lsd_mkb
list(APPEND PDD_CONV_DIFF_EXTERNAL_LIBRARIES ${LAPACKMKL_LIBRARIES} gfortran)            #pdd_conv_diff
list(APPEND PDD_LAPLACE_EXTERNAL_LIBRARIES ${LAPACKMKL_LIBRARIES} gfortran)              #pdd_laplace
list(APPEND SID_LAPACK_EXTERNAL_LIBRARIES ${LAPACKMKL_LIBRARIES})               #sid_lapack
list(APPEND PDD_CBS_EXTERNAL_LIBRARIES ${LAPACKMKL_LIBRARIES})                  #pdd_cbs
list(APPEND PDD_TURBULENT_LIB_EXTERNAL_LIBRARIES ${LAPACKMKL_LIBRARIES})        #pdd_turbulent_lib
list(APPEND PDD_CBS_LIB_EXTERNAL_LIBRARIES ${LAPACKMKL_LIBRARIES})              #pdd_cbs_lib

# -----------
# -- Boost --
# -----------

#if( CREATE_MOD_FEM_CBS_LIB OR 
#    CREATE_MOD_FEM_CBS_PRISM OR
#    CREATE_MOD_FEM_CBS_HYBRID OR
#    CREATE_MOD_FEM_TURBULENT_LIB) #TODO itd....
  
  set(Boost_USE_MULTITHREADED ON)
  #set(Boost_ADDITIONAL_VERSIONS ${BOOST_VER_NO})
  #SET(Boost_ADDITIONAL_VERSIONS "0.99" "0.99.0" "1.78" "1.78.0") #dawac tez zero
#  set(Boost_USE_STATIC_LIBS ${MODFEM_USE_STATIC})

  #find_package(Boost 1.40.0 REQUIRED COMPONENTS program_options)
  #find_package(Boost REQUIRED COMPONENTS program_options)
  find_package(Boost REQUIRED COMPONENTS filesystem system regex)
  if(Boost_FOUND)
    include_directories(${Boost_INCLUDE_DIR})
    link_directories(${Boost_LIBRARY_DIRS})

    set(UTD_UTIL_EXTERNAL_INCLUDE_DIRS ${UTD_UTIL_EXTERNAL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
    list(APPEND UTD_UTIL_EXTERNAL_LIBRARIES ${Boost_LIBRARIES})
    add_definitions("-DHAS_BOOST")
  endif()  

#  if(Boost_FOUND)
    #set EXTERNAL_INCLUDE_DIRS of all supertargets that use library
#    set(PDD_CBS_EXTERNAL_INCLUDE_DIRS ${PDD_CBS_EXTERNAL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
#    set(PDD_TURBULENT_LIB_EXTERNAL_INCLUDE_DIRS ${PDD_TURBULENT_LIB_EXTERNAL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
#    set(PDD_CBS_LIB_EXTERNAL_INCLUDE_DIRS ${PDD_CBS_LIB_EXTERNAL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
    #set EXTERNAL_LIBRARIES of all targets that use library
#    list(APPEND PDD_CBS_EXTERNAL_LIBRARIES ${Boost_LIBRARIES})     #pdd_cbs
#    list(APPEND PDD_TURBULENT_LIB_EXTERNAL_LIBRARIES ${Boost_LIBRARIES}) #pdd_turbulent_lib 
#    list(APPEND PDD_CBS_LIB_EXTERNAL_LIBRARIES ${Boost_LIBRARIES})       #pdd_cbs_lib

    #list(APPEND PDD_CBS_PRISM_EXTERNAL_LIBRARIES ${Boost_LIBRARIES})     #pdd_cbs
    #list(APPEND PDD_CBS_HYBRID_EXTERNAL_LIBRARIES ${Boost_LIBRARIES})    #pdd_cbs
    #list(APPEND PDD_TURBULENT_LIB_EXTERNAL_LIBRARIES ${Boost_LIBRARIES}) #pdd_turbulent_lib 
    #list(APPEND PDD_CBS_LIB_EXTERNAL_LIBRARIES ${Boost_LIBRARIES})       #pdd_cbs_lib
#  endif()
  #link_directories(${boost_lib_dir})
#endif()


# -----------
# --  MPI  --
# -----------
if(MODFEM_NEW_MPI)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMODFEM_NEW_MPI=true")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMODFEM_NEW_MPI=true")
endif()
if(DEFINED MODFEM_MPI)
  find_package(MPI REQUIRED)
  include_directories(${MPI_INCLUDE_PATH})
  if(${MODFEM_MPI} STREQUAL "mpi")
    set(MODFEM_MPI_CODE_DEFINE PARALLEL)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPARALLEL")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPARALLEL")
    if(MODFEM_NEW_MPI)
      message("MODFEM_NEW_MPI set to TRUE")
      find_package(METIS REQUIRED)
      find_package(PARMETIS REQUIRED)
      list(APPEND MODFEM_MPI_LIBS_STD mmpl_adapter appl_std_lin pcl_mpi_safe ${METIS_LIBRARY} ${PARMETIS_LIBRARY} gfortran)
      list(APPEND MODFEM_MPI_LIBS_DG mmpl_adapter appl_dg_prism pcl_mpi_safe ${METIS_LIBRARY} ${PARMETIS_LIBRARY} gfortran)
      add_subdirectory(mmpd_adapter)
      add_subdirectory(pcd_mpi_safe)
    else()
      message("MODFEM_NEW_MPI set to FALSE")
      list(APPEND MODFEM_MPI_LIBS_STD mmpl_prism appl_std_lin pcl_mpi gfortran)
      list(APPEND MODFEM_MPI_LIBS_DG mmpl_prism appl_dg_prism pcl_mpi gfortran)
      add_subdirectory(pcd_mpi)
    endif() 
          
  elseif(${MODFEM_MPI} STREQUAL "nompi")
    set(MODFEM_MPI_CODE_DEFINE NPARALLEL)
  else()
    message("MODFEM_MPI: ${MODFEM_MPI} ")
    message(FATAL_ERROR "MODFEM_MPI incorecctly defined. Allowed values: mpi, nompi.")
  endif()
else()
 message(FATAL_ERROR "MODFEM_MPI not defined. Allowed values: mpi, nompi.")
endif()

# -- check for wrong config file settings

if(MODFEM_ITER_SOLVER_MODULE STREQUAL "sil_krylow_bliter")
  if(NOT MODFEM_USE_STATIC)
    message(FATAL_ERROR "For sil_krylow_bliter (due to cyclic dependency) you need to set MODFEM_USE_STATIC to TRUE. Please edit your config file.")
  endif()
endif()

if(MODFEM_DIRECT_SOLVER_MODULE STREQUAL "sil_pardiso")
  if(NOT MODFEM_BLASLAPACK STREQUAL "MKL")
    message(FATAL_ERROR "For sil_pardiso MODFEM_BLASLAPACK needs to be set to MKL. Please edit your config file.")
  endif()
endif()

# -- check for pdd_cbs_lib and pdd_turbulent_lib dependencies

if(CREATE_MOD_FEM_NS_SUPG_PRISM_STD_TURBULENT OR
   CREATE_MOD_FEM_NS_SUPG_HYBRID_STD_TURBULENT OR
   CREATE_MOD_FEM_CBS_PRISM OR
   CREATE_MOD_FEM_CBS_HYBRID OR
   CREATE_MOD_FEM_TURBULENT_LIB) 

 if(NOT CREATE_MOD_FEM_TURBULENT_LIB)
   message(FATAL_ERROR "One of selected targets needs pdd_cbs_lib and/or pdd_turbulent_lib targets. Please enable them in your config file.")
 endif()

 if(NOT CREATE_MOD_FEM_CBS_LIB)
   message(FATAL_ERROR "One of selected targets needs pdd_cbs_lib and/or pdd_turbulent_lib targets. Please enable them in your config file.")
 endif()
endif()

# -- configure opencl
if(MODFEM_ACCEL)
  if(NOT ${MODFEM_ACCEL} STREQUAL "none")
    set(accel "openmp")
    
    #Set multithread flag
    add_definitions(-DMULTITHREADED=true)

    #Set appropriate opencl flag
    if(${MODFEM_ACCEL} STREQUAL "opencl")
      set(accel "opencl")
      
      #Check machine
      if(${OPENCL_MACHINE} STREQUAL "cpu")
	add_definitions(-DOPENCL_CPU=true)
      elseif(${OPENCL_MACHINE} STREQUAL "gpu")
	add_definitions(-DOPENCL_GPU=true)
      elseif(${OPENCL_MACHINE} STREQUAL "phi")
	add_definitions(-DOPENCL_PHI=true)
      else()
	message(FATAL_ERROR "OPENCL_MACHINE not defined. Allowed values is: cpu, gpu, phi.")
      endif()

      #???
      #add_definitions(-DTUNING=true)
      
    #Set appropriate opencl flag
    elseif(${MODFEM_ACCEL} STREQUAL "cuda")
      #add_subdirectory(tmd_cuda)
      message(FATAL_ERROR "MODFEM_ACCEL: cuda not yet implemented.")
    endif()
  else()
    set(accel "none")
  endif()
else()
  message(FATAL_ERROR "MODFEM_ACCEL not defined. Allowed values: none, opencl, cuda.")
endif()


########################################################
# ----------------------- TARGETS -------------------- #
########################################################

#######################################
# -- APPROX, MESH AND UTIL TARGETS -- #
#######################################

# -- tmd_omp ----
add_subdirectory(tmd_omp)
# -- utd_util ----
add_subdirectory(utd_util) 
# -- utd_system ----
add_subdirectory(utd_system)
# -- mmd_prism ------
add_subdirectory(mmd_prism)
# -- mmd_t4_prism ------
add_subdirectory(mmd_t4_prism)
# -- mmd_prism_2D ----
add_subdirectory(mmd_prism_2D)
# -- mmd_remesh ------
add_subdirectory(mmd_remesh)
# -- apd_std_quad ----
add_subdirectory(apd_std_quad)
# -- apd_std_lin ----
add_subdirectory(apd_std_lin)

# -- apd_dg_prism ----
add_subdirectory(apd_dg_prism)
if( CREATE_MOD_FEM_NS_SUPG_HEAT_VOF_PRISM_STD OR
    CREATE_MOD_FEM_NS_SUPG_HEAT_VOF_HYBRID_STD OR
    CREATE_MOD_FEM_NS_SUPG_HEAT_VOF_PRISM2D_STD
    )
    add_subdirectory(pdd_vof)
endif()

# -- mod_fem_viewer ---
list(APPEND MOD_FEM_TOOLS_LIST "CREATE_MOD_FEM_VIEWER")

if(CREATE_MOD_FEM_VIEWER)
  if(MOD_FEM_VIEWER_USE_AS_LIB)
    set(MOD_FEM_VIEWER_LIB "mod_fem_viewer")
    add_definitions(-DMOD_FEM_VIEWER)
  else()
    set(MOD_FEM_VIEWER_APP "FemViewer")
  endif()  
  
  add_subdirectory(mod_fem_viewer)
  # add mod_fem_viewer to targets
  list(APPEND PDD_LAPLACE_EXTERNAL_LIBRARIES ${MOD_FEM_VIEWER_LIB})
  list(APPEND PDD_NS_SUPG_HEAT_EXTERNAL_LIBRARIES  ${MOD_FEM_VIEWER_LIB})
  list(APPEND PDD_CONV_DIFF_EXTERNAL_LIBRARIES ${MOD_FEM_VIEWER_LIB})            #pdd_conv_diff
  list(APPEND PDD_CBS_EXTERNAL_LIBRARIES ${MOD_FEM_VIEWER_LIB})                  #pdd_cbs
  list(APPEND PDD_TURBULENT_LIB_EXTERNAL_LIBRARIES ${MOD_FEM_VIEWER_LIB})        #pdd_turbulent_lib
  list(APPEND PDD_CBS_LIB_EXTERNAL_LIBRARIES ${MOD_FEM_VIEWER_LIB})              #pdd_cbs_lib
endif()

# -- modfem mpi ---
if(${MODFEM_MPI} STREQUAL "mpi")
  #add_subdirectory(mmpd_adapter)
  add_subdirectory(mmpd_prism)
  add_subdirectory(appd_std_lin)
  add_subdirectory(appd_dg_prism)
 # add_subdirectory(pcd_mpi) #this was done above
endif()

# -- modfem openmp && opencl --- 
if(MODFEM_ACCEL)
  if(${MODFEM_ACCEL} STREQUAL "opencl")
    # -- tmd_ocl ----
    add_subdirectory(tmd_ocl)
  elseif(${MODFEM_ACCEL} STREQUAL "cuda")
    #add_subdirectory(tmd_cuda)
    message(FATAL_ERROR "MODFEM_ACCEL: cuda not yet implemented.")
  endif()
else()
  message(FATAL_ERROR "MODFEM_ACCEL not defined. Allowed values: none, opencl, cuda.")
endif()


########################
# -- SOLVER TARGETS -- #
########################

if(MODFEM_DIRECT_SOLVER_MODULE STREQUAL "sil_pardiso")
  # -- sid_pardiso ----
  add_subdirectory(sid_pardiso)
elseif(MODFEM_DIRECT_SOLVER_MODULE STREQUAL "sil_lapack")
  # -- sid_lapack ----
  add_subdirectory(sid_lapack)
else()
  message(FATAL_ERROR "MODFEM_DIRECT_SOLVER_MODULE is wrong. Please check your configuration file.")
endif()

if(MODFEM_ITER_SOLVER_MODULE STREQUAL "sil_krylow_bliter")
  # -- sid_krylow_bliter ----
  add_subdirectory(lsd_mkb)
  add_subdirectory(sid_krylow_bliter)
else()
  message(FATAL_ERROR "MODFEM_ITER_SOLVER_MODULE is wrong. Please check your configuration file.")
endif()

#####################
# -- PDD TARGETS -- #
#####################
# -- (which of them are created is decided in their CMake files)

add_subdirectory(pdd_conv_diff)
add_subdirectory(pdd_ns_supg)
add_subdirectory(pdd_heat)
add_subdirectory(pdd_laplace)
add_subdirectory(pdd_elast)
add_subdirectory(pdd_ns_supg_ale)
add_subdirectory(pdd_ns_supg_heat)
add_subdirectory(pdd_ns_supg_heat_vof)

#Binaries appendixes
set(CMAKE_DEBUG_POSTFIX "_d" )
set(CMAKE_RELWITHDEBINFO_POSTFIX "_i" )

# -- summary of settings
if(CMAKE_BUILD_TYPE STREQUAL "Release")
  set(CMAKE_Fortran_FLAGS_ALL "${CMAKE_Fortran_FLAGS} ${CMAKE_Fortran_FLAGS_RELEASE}")
  set(CMAKE_CXX_FLAGS_ALL "${CMAKE_CXX_FLAGS_ALL} ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}")
  set(CMAKE_EXE_LINKER_FLAGS_ALL "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
  set(CMAKE_Fortran_FLAGS_ALL "${CMAKE_Fortran_FLAGS} ${CMAKE_Fortran_FLAGS_RELWITHDEBINFO}")
  set(CMAKE_CXX_FLAGS_ALL "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
  set(CMAKE_EXE_LINKER_FLAGS_ALL "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")
elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
  set(CMAKE_Fortran_FLAGS_ALL "${CMAKE_Fortran_FLAGS} ${CMAKE_Fortran_FLAGS_DEBUG}")
  set(CMAKE_CXX_FLAGS_ALL "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}")
  set(CMAKE_EXE_LINKER_FLAGS_ALL "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_DEBUG}")
else()
  set(CMAKE_Fortran_FLAGS_ALL "Unknown")
  set(CMAKE_CXX_FLAGS_ALL "Unknown")
  set(CMAKE_EXE_LINKER_FLAGS_ALL "Unknown")
endif()

#get_property(PDD_HMT_DEFINITIONS DIRECTORY pdd_hmt PROPERTY COMPILE_DEFINITIONS)
#get_property(SID_PARDISO_DEFINITIONS DIRECTORY sid_pardiso PROPERTY COMPILE_DEFINITIONS)

if(NOT WIN32)
  string(ASCII 27 Esc)
  set(ColourReset "${Esc}[m")
  set(ColourBold  "${Esc}[1m")
  set(Red         "${Esc}[31m")
  set(Green       "${Esc}[32m")
  set(Yellow      "${Esc}[33m")
  set(Blue        "${Esc}[34m")
  set(Magenta     "${Esc}[35m")
  set(Cyan        "${Esc}[36m")
  set(White       "${Esc}[37m")
  set(BoldRed     "${Esc}[1;31m")
  set(BoldGreen   "${Esc}[1;32m")
  set(BoldYellow  "${Esc}[1;33m")
  set(BoldBlue    "${Esc}[1;34m")
  set(BoldMagenta "${Esc}[1;35m")
  set(BoldCyan    "${Esc}[1;36m")
  set(BoldWhite   "${Esc}[1;37m")
endif()

message("")
message("=> Config file in use: ${ENV_PLATFORM}.cmake")
message("=> Iterative solver module in use: ${MODFEM_ITER_SOLVER_MODULE}")
message("=> Direct solver module in use: ${MODFEM_DIRECT_SOLVER_MODULE}")
message("=> BLAS/LAPACK from: ${MODFEM_BLASLAPACK}")
message("=> Compilation:")
message("   - CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
message("   - MODFEM_USE_STATIC: ${MODFEM_USE_STATIC}")
message("   - Fortran:")
message("     - Compiler: ${CMAKE_Fortran_COMPILER}")
message("     - Flags: ${CMAKE_Fortran_FLAGS_ALL}")
message("   - C++:")
message("     - Compiler: ${CMAKE_CXX_COMPILER}")
message("     - Flags: ${CMAKE_CXX_FLAGS_ALL}")
message("   - Link:")
message("     - Flags for exe: ${CMAKE_EXE_LINKER_FLAGS_ALL}")
message("     - Flags added manually: ${LINK_FLAGS}")
message("   - MODFEM_MPI: ${MODFEM_MPI}")
message("   - MODFEM_ACCEL: ${MODFEM_ACCEL}")
if(${MODFEM_ACCEL} STREQUAL "opencl")
  message("     - OpenCL headers directory: ${OPENCL_INCLUDE_DIRS}")
  message("     - OpenCL libraries directory: ${OPENCL_LIBRARY_DIRS}")
  message("     - OpenCL library file: ${OPENCL_LIBRARIES}")
  if(${OPENCL_MACHINE} STREQUAL "cpu")
    message("     - OpenCL acceleration enabled for CPU (intel/amd)")
  elseif(${OPENCL_MACHINE} STREQUAL "gpu")
    message("     - OpenCL acceleration enabled for GPU (intel/nvidia/amd)")
  elseif(${OPENCL_MACHINE} STREQUAL "phi")
    message("     - OpenCL acceleration enabled for ACCELERATOR (intel xeon phi)")
  endif()
endif()

#message("   - Definitions:")
#message("     - pdd_hmt: ${PDD_HMT_DEFINITIONS}")
#message("     - sid_pardiso: ${SID_PARDISO_DEFINITIONS}")

message("=> List of created auxiliary tools:")

list(LENGTH MOD_FEM_TOOLS_LIST number_of_tools)
math(EXPR number_of_tools "${number_of_tools} - 1")
foreach(iter RANGE ${number_of_tools})
  list(GET MOD_FEM_TOOLS_LIST ${iter} loc_name)
  if(${loc_name} STREQUAL "TRUE")
    message(STATUS "${Green}${loc_name}${ColourReset} flag is ${Green}${${loc_name}}${ColourReset}")
  elseif(${loc_name} STREQUAL "FALSE")
    message(STATUS "${Red}${loc_name}${ColourReset} flag is ${Red}${${loc_name}}${ColourReset}")
  else()
    message(STATUS "${Yellow}${loc_name}${ColourReset} flag is ${Yellow}UNDEFINED${ColourReset}")
  endif()
  unset(loc_name)
endforeach(iter)
unset(iter)
unset(number_of_tools)

message("=> List of created executable files:")

list(LENGTH MOD_FEM_EXEC_LIST number_of_exec)
math(EXPR number_of_exec "${number_of_exec} - 1")
foreach(iter RANGE ${number_of_exec})
  list(GET MOD_FEM_EXEC_LIST ${iter} loc_name)
  if(${loc_name} STREQUAL "TRUE")
    message(STATUS "${Green}${loc_name}${ColourReset} flag is ${Green}${${loc_name}}${ColourReset}")
  elseif(${loc_name} STREQUAL "FALSE")
    message(STATUS "${Red}${loc_name}${ColourReset} flag is ${Red}${${loc_name}}${ColourReset}")
  else()
    message(STATUS "${Yellow}${loc_name}${ColourReset} flag is ${Yellow}UNDEFINED${ColourReset}")
  endif()
  unset(loc_name)
endforeach(iter)
unset(iter)
unset(number_of_exec)

message("--------------------------------------------------------------------")
message("")

INCLUDE(CTest)
